package graphgenetics;

import java.util.Random;


/**
 * Builds randomly ordered arrays of the numbers {0..N-1}
 * @author Jeremy Mikkola
 */
public class RandomArrayBuilder {

    private Random r;
    private int size;

    /**
     * Create a new RandomArrayBuilder.
     * @param r Source of random numbers.
     * @param size The size to make the arrays.
     */
    public RandomArrayBuilder(Random r, int size) {
        this.r = r;
        this.size = size;
    }

    /**
     * Create a new RandomArrayBuilder without specifying a Random object
     * @param size The size to make the arrays
     */
    public RandomArrayBuilder(int size) {
        this(new Random(), size);
    }


    /**
     * Makes an array of the numbers {0..size-1} in a random order.
     * @return The random array
     */
    public int[] makeArray() {
        int[] arr = new int[size];
        Q que = new Q(size);
        for (int i = 0; i < size; i++) {
            arr[i] = que.pop(r.nextInt(que.size));
        }
        return arr;
    }

    /**
     * Makes an array of the numbers {0..size-1} in a random order
     * with the first element as specified.
     * @param first The first number to be placed in the array.
     * @return The random array
     */
    public int[] makeArray(int first) {
        int[] arr = new int[size];
        Q que = new Q(size);
        if (first >= size) first %= size;
        arr[0] = que.pop(first);
        for (int i = 1; i < size; i++) {
            arr[i] = que.pop(r.nextInt(que.size));
        }
        return arr;
    }


    /**
     * The is a queue class for storing the unpicked numbers when making an
     * array. 
     */
    private class Q {
        int[] numbers;
        int size;

        /**
         * Creates a new Q with the numbers {0..size-1}
         * @param size The size of the que
         */
        public Q(int size) {
            this.size = size;
            numbers = new int[size];
            for (int i = 0; i < size; i++) {
                numbers[i] = i;
            }
        }

        /**
         * Removes and returns the number at the index
         * @param index The index of the number
         * @return The number at the index.
         */
        public int pop(int index) {
            int out = numbers[index];
            size--;
            numbers[index] = numbers[size];
            return out;
        }


    }


}
